home *** CD-ROM | disk | FTP | other *** search
- #include<stdio.h>
-
- /* chouse_n ( char *strng, int length) returns a pointer to a string of */
- /* length characters chosen from "strng" , duplicate chars in "strng" are */
- /* significant. Strings are generated in lexical order. */
- /* First call, call with *strng. each subsiquent call, call with NULL, */
- /* returns one combination. Calls after all combinations have been */
- /* returned return NULL. Will return NULL for errors. */
- /* not very defensive (i.e. WILL BREAK) */
-
- /* dave chapman aug '91 released to public domain */
-
- char *chouse_n( char *strng, int length);
-
- char *chouse_n( char *strng, int length)
- {
- static char *str;
- static char *curr;
- static char *pos; /* for each char in curr(ent string),
- its pos in str */
- static int counts[256];
- int i,j;
-
- if (0 >= length)
- return NULL;
-
- if (NULL != strng)
- {
- str = malloc(strlen(strng)); /* first call, prep string for use */
- curr = malloc(2 * length + 1);
- pos = curr + length +1;
-
- for (i = 0; i < 256; counts[i++] = 0)
- ;
- for (i = 0; strng[i]; i++)
- counts[strng[i]]++;
-
- for (i = 1, j = 0; i < 256; i++)
- {
- if (counts[i])
- {
- str[j] = i;
- counts[j++] = counts[i];
- }
- }
- str[j] = '\0'; /* str is string of distinct chars in order */
- /* counts[] holds count of each char */
-
- /* take first length chars */
-
- for (i = 0,j = 0; i < length; i++)
- {
- curr[i] = str[j];
- pos[i] = j;
- if (!(--counts[j]))
- j++;
- }
- curr[i] = '\0';
- return curr;
- }
- /* if called with "mississippi",5;
- str -> "imps"
- curr -> "iiiim"
- counts -> 0,0,2,4;
- pos -> 0,0,0,0,1; */
-
- /* go back to front */
-
- for (j = length; j > 0;)
- {
- counts[ pos[--j]]++; /* "replace" char */
-
- /* look for a new char for curr posit. */
-
- for ( i = ++pos[j]; str[i] && ! counts[i]; i++);
- if (curr[j] = str[i]) /* found a char */
- {
- --counts[i];
- pos[j] = i;
-
- /* placed char, fill out rest of string */
-
- for (++j, i = 0; j < length; j++)
- {
- for ( ; !counts[i]; i++)
- ;
- curr[j] = str[i]; /* first available char */
- --counts[i];
- pos[j] = i;
- }
- return curr;
- }
- /* no more chars for this pos ; go back one */
- }
- /* done */
- return NULL;
- }
-
- void main(void)
- {
- char *str = "aabbccdd";
- int i,j;
-
- j = 0;
- i = 5;
- puts(chouse_n( str, i));
- while (str = chouse_n(NULL, i))
- {
- ++j;
- printf(" %s %d\n",str,j);
- }
- }
-